package cn.tedu.mall.order.service.impl;

import cn.tedu.mall.common.exception.CoolSharkServiceException;
import cn.tedu.mall.common.pojo.domain.CsmallAuthenticationInfo;
import cn.tedu.mall.common.restful.JsonPage;
import cn.tedu.mall.common.restful.ResponseCode;
import cn.tedu.mall.order.mapper.OmsCartMapper;
import cn.tedu.mall.order.service.IOmsCartService;
import cn.tedu.mall.pojo.order.dto.CartAddDTO;
import cn.tedu.mall.pojo.order.dto.CartUpdateDTO;
import cn.tedu.mall.pojo.order.model.OmsCart;
import cn.tedu.mall.pojo.order.vo.CartStandardVO;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.C;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@Slf4j
public class OmsCartServiceImpl implements IOmsCartService {

    @Autowired
    private OmsCartMapper omsCartMapper;

    // 新增sku信息到购物车
    @Override
    public void addCart(CartAddDTO cartDTO) {
        // 实现新增购物车信息,要先判断这个skuId是否已经在当前用户购物车中包含了
        // 那么就必须先获取当前登录用户的userId
        // 需要编写方法从SpringSecurity上下文中获取
        Long userId=getUserId();
        // 根据userId和cartDTO参数中的skuId,进行查询
        OmsCart omsCart=omsCartMapper.selectExistsCart(userId,cartDTO.getSkuId());
        // 如果omsCart查询不为null,就表示这个商品已经存在于购物车了
        // 判断omsCart是否为null
        if(omsCart == null){
            // omsCart如果为null,表示购物车中没有这个商品,进行新增操作
            // 我们需要将cartDTO中的同名输出赋值到omsCart中,以便进行新增
            // 但是omsCart是null的话,赋值的过程会报null指针,所以要先实例化
            omsCart=new OmsCart();
            BeanUtils.copyProperties(cartDTO,omsCart);
            // cartDTO中没有userId的信息,需要单独赋值
            omsCart.setUserId(userId);
            // 执行新增操作
            omsCartMapper.saveCart(omsCart);
        }else{
            // omsCart不是null,就要对当前购物车中商品进行数量的修改
            // 数量的值是当前购物车中数量+cartDTO参数中新增的数量
            // 因为数据库修改操作直接是赋值,所以在连库前,需要把数量加好
            // 我们将omsCart中的数量和cartDTO中的数量相加,在赋值给omsCart对象的quantity属性
            omsCart.setQuantity(omsCart.getQuantity()+cartDTO.getQuantity());
            // 按赋值后的信息执行修改
            omsCartMapper.updateQuantityById(omsCart);
        }

    }
    // 分页查询当前用户购物车信息
    @Override
    public JsonPage<CartStandardVO> listCarts(Integer page, Integer pageSize) {
        // 先从SpringSecurity上下文中获取当前登录用户Id
        Long userId=getUserId();
        // 设置查询分页的数据范围(page,pageSize)
        PageHelper.startPage(page,pageSize);
        // 上面的设置完成后,下面进行查询操作,会自动添加limit关键字在sql语句末尾
        List<CartStandardVO> list=omsCartMapper.selectCartsByUserId(userId);
        // 返回JsonPage类型对象
        return JsonPage.restPage(new PageInfo<>(list));
    }

    // 支持批量删除购物车信息的方法
    @Override
    public void removeCart(Long[] ids) {
        // 无需遍历ids直接将ids作为参数传给mapper方法
        int rows=omsCartMapper.deleteCartsByIds(ids);
        if(rows==0){
            throw new CoolSharkServiceException(
                    ResponseCode.NOT_FOUND,"您要删除的商品已经删除了!");
        }
    }

    @Override
    public void removeAllCarts() {
        Long userId=getUserId();
        int rows=omsCartMapper.deleteCartsByUserId(userId);
        if(rows==0){
            throw new CoolSharkServiceException(
                    ResponseCode.NOT_FOUND,"您的购物车是空的!");
        }
    }

    // 根据userId和skuId删除购物车商品的方法(新增订单用)
    @Override
    public void removeUserCarts(OmsCart omsCart) {
        // 直接调用删除购物车中商品方法即可
        // 无需判断受影响行数,也不要抛出异常,购物车删除失败也不影响新增订单的流程
        omsCartMapper.deleteCartByUserIdAndSkuId(omsCart);
    }

    @Override
    public void updateQuantity(CartUpdateDTO cartUpdateDTO) {
        // 执行修改购物车商品数量的mapper方法参数是OmsCart类型
        OmsCart omsCart=new OmsCart();
        // 参数cartUpdateDTO中包含id和quantity属性,赋值给omsCart就可以执行修改了
        BeanUtils.copyProperties(cartUpdateDTO,omsCart);
        // omsCart执行修改
        omsCartMapper.updateQuantityById(omsCart);
    }


    // 如果需要再业务逻辑层代码中获取用户信息
    // 就可以编写下面的方法,从SpringSecurity上下文中获取
    // 这个用户信息是以JWT的方式从前端发到控制器的,我们的过滤器会解析JWT
    // 并将解析出的用户信息保存在SpringSecurity上下文中
    public CsmallAuthenticationInfo getUserInfo(){
        // 获取SpringSecurity上下文
        UsernamePasswordAuthenticationToken authenticationToken=
                (UsernamePasswordAuthenticationToken)
                   SecurityContextHolder.getContext().getAuthentication();
        // 为了逻辑更加严谨,判断一下SpringSecurity上下文内容是否为null
        if(authenticationToken == null){
            throw new CoolSharkServiceException(
                    ResponseCode.UNAUTHORIZED,"您还未登录");
        }
        // 从SpringSecurity上下文中获取用户信息
        CsmallAuthenticationInfo csmallAuthenticationInfo=
                (CsmallAuthenticationInfo) authenticationToken.getCredentials();
        // 最终返回用户信息
        return csmallAuthenticationInfo;
    }
    // 业务逻辑层实际开发时,大部分都是需要用户的Id而已
    // 所以我们再编写一个方法,只返回用户的Id
    public Long getUserId(){
        return getUserInfo().getId();
    }





}
